package com.xingyang;

import com.xingyang.yutnori.model.*;
import com.xingyang.yutnori.ui.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.border.EmptyBorder;
import java.util.ArrayList;
import java.util.List;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

/**
 * The main application class for the Korean traditional Yut Nori game.
 * This class initializes and manages the game window and core components.
 * 
 * @author Xingyang
 */
public class YutNoriApp extends JFrame {
    private GameBoard gameBoard;
    private YutStickPanel yutStickPanel;
    private JButton newGameButton;
    private JButton endTurnButton;
    private JPanel controlPanel;
    
    /**
     * Constructs and initializes the main game application.
     */
    public YutNoriApp() {
        // Set up the main window
        setTitle("한국 전통 윷놀이 (Korean Yut Nori Game)");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(1350, 900));
        
        // Show player selection dialog first
        showPlayerSelectionDialog();
        
        // Display the window for best visibility
        setSize(1450, 950);
        setLocationRelativeTo(null);
        setVisible(true);
    }
    
    /**
     * Shows the player selection dialog and initializes the game with selected players.
     */
    private void showPlayerSelectionDialog() {
        PlayerSelectionDialog dialog = new PlayerSelectionDialog(this);
        boolean confirmed = dialog.showDialog();
        
        if (confirmed) {
            // Get selected player info
            int playerCount = dialog.getPlayerCount();
            String[] playerNames = dialog.getPlayerNames();
            Color[] playerColors = dialog.getPlayerColors();
            
            // Initialize game with selected players
            initializeGame(playerCount, playerNames, playerColors);
        } else {
            // Default initialization if canceled
            initializeGame();
        }
        
        // Create and layout components after game initialization
        createComponents();
        layoutComponents();
        setupEventListeners();
    }
    
    /**
     * Initializes a new game instance with default players.
     */
    private void initializeGame() {
        // Create two players
        List<Player> players = new ArrayList<>();
        Player player1 = new Player("Player 1", new Color(220, 50, 50));
        Player player2 = new Player("Player 2", new Color(50, 100, 220));
        
        players.add(player1);
        players.add(player2);
        
        // Create a new game with these players
        Game game = new Game(players);
        
        // Initialize the game board
        gameBoard = new GameBoard(game);
        
        System.out.println("New game initialized with " + players.size() + " players");
        System.out.println("Current player: " + game.getCurrentPlayer().getName());
    }
    
    /**
     * Initializes a new game instance with the specified players.
     */
    private void initializeGame(int playerCount, String[] playerNames, Color[] playerColors) {
        // Create players based on selection
        List<Player> players = new ArrayList<>();
        
        for (int i = 0; i < playerCount; i++) {
            Player player = new Player(playerNames[i], playerColors[i]);
            players.add(player);
        }
        
        // Create a new game with these players
        Game game = new Game(players);
        
        // Initialize the game board
        gameBoard = new GameBoard(game);
        
        System.out.println("New game initialized with " + players.size() + " players");
        System.out.println("Current player: " + game.getCurrentPlayer().getName());
    }
    
    /**
     * Creates all UI components.
     */
    private void createComponents() {
        // Create the Yut stick panel
        yutStickPanel = new YutStickPanel(gameBoard);
        
        // Create control buttons
        newGameButton = createStyledButton("새 게임 (New Game)", new Color(100, 180, 100));
        endTurnButton = createStyledButton("턴 끝내기 (End Turn)", new Color(180, 100, 100));
        endTurnButton.setEnabled(false);
        endTurnButton.setName("End Turn Button");
        
        // Create the control panel that will hold buttons
        controlPanel = new JPanel();
        controlPanel.setLayout(new GridLayout(0, 1, 10, 10));
        controlPanel.setBorder(new EmptyBorder(15, 15, 15, 15));
        controlPanel.setBackground(new Color(245, 240, 220));
    }
    
    /**
     * Creates a styled button with custom appearance.
     */
    private JButton createStyledButton(String text, Color color) {
        JButton button = new JButton(text);
        button.setFont(new Font("SansSerif", Font.BOLD, 16));
        button.setBackground(color);
        button.setForeground(Color.WHITE);
        button.setFocusPainted(false);
        button.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(Color.DARK_GRAY, 1),
            BorderFactory.createEmptyBorder(10, 10, 10, 10)
        ));
        
        // Add hover effect
        button.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                button.setBackground(color.brighter());
            }
            
            @Override
            public void mouseExited(MouseEvent e) {
                button.setBackground(color);
            }
        });
        
        return button;
    }
    
    /**
     * Lays out all components in the main window.
     */
    private void layoutComponents() {
        // Use BorderLayout as the main layout
        setLayout(new BorderLayout());
        
        // Create header panel
        JPanel headerPanel = createHeaderPanel();
        add(headerPanel, BorderLayout.NORTH);
        
        // Create main content panel with game board and controls
        JPanel mainPanel = new JPanel(new BorderLayout(20, 0));
        mainPanel.setBackground(new Color(245, 235, 215));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
        
        // Create game board panel with fixed size constraint
        JPanel gameBoardWrapper = new JPanel();
        gameBoardWrapper.setLayout(new GridBagLayout()); // Use GridBagLayout to center the board
        gameBoardWrapper.setBackground(new Color(245, 235, 215));
        
        // Add the game board to its wrapper with constraints to maintain aspect ratio
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.fill = GridBagConstraints.NONE;
        gbc.anchor = GridBagConstraints.CENTER;
        gameBoardWrapper.add(gameBoard, gbc);
        
        // Create right panel for controls
        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
        rightPanel.setBackground(new Color(245, 240, 220));
        rightPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        rightPanel.setPreferredSize(new Dimension(380, 600));
        
        // Add yut stick panel
        yutStickPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
        rightPanel.add(yutStickPanel);
        rightPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        
        // Create button panel
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
        buttonPanel.setOpaque(false);
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 15, 0));
        
        // Style buttons
        newGameButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        newGameButton.setPreferredSize(new Dimension(320, 40));
        newGameButton.setMaximumSize(new Dimension(320, 40));
        buttonPanel.add(newGameButton);
        buttonPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        
        endTurnButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        endTurnButton.setPreferredSize(new Dimension(320, 40));
        endTurnButton.setMaximumSize(new Dimension(320, 40));
        buttonPanel.add(endTurnButton);
        
        rightPanel.add(buttonPanel);
        rightPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        
        // Add instructions panel
        JPanel instructionsPanel = createInstructionsPanel();
        instructionsPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
        instructionsPanel.setMaximumSize(new Dimension(380, 300));
        rightPanel.add(instructionsPanel);
        
        // Add components to main panel
        mainPanel.add(gameBoardWrapper, BorderLayout.CENTER);
        mainPanel.add(rightPanel, BorderLayout.EAST);
        
        // Add main panel to frame
        add(mainPanel, BorderLayout.CENTER);
        
        // Add footer
        JPanel footerPanel = createFooterPanel();
        add(footerPanel, BorderLayout.SOUTH);
    }
    
    /**
     * Creates a decorative header panel with traditional Korean styling.
     */
    private JPanel createHeaderPanel() {
        JPanel headerPanel = new JPanel(new BorderLayout());
        headerPanel.setBackground(new Color(200, 180, 150));
        headerPanel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createMatteBorder(0, 0, 2, 0, new Color(139, 69, 19)),
            BorderFactory.createEmptyBorder(10, 20, 10, 20)
        ));
        
        // Create a title label with Korean and English text
        JLabel titleLabel = new JLabel("윷놀이 (Yut Nori) - 한국 전통 게임", JLabel.CENTER);
        titleLabel.setFont(new Font("SansSerif", Font.BOLD, 28));
        titleLabel.setForeground(new Color(80, 30, 0));
        
        headerPanel.add(titleLabel, BorderLayout.CENTER);
        
        return headerPanel;
    }
    
    /**
     * Creates a panel with brief game instructions.
     */
    private JPanel createInstructionsPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.setBackground(new Color(255, 250, 240));
        panel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(139, 69, 19), 1),
            BorderFactory.createEmptyBorder(10, 10, 10, 10)
        ));
        
        JLabel titleLabel = new JLabel("게임 방법 (How to Play)", JLabel.CENTER);
        titleLabel.setFont(new Font("SansSerif", Font.BOLD, 16));
        titleLabel.setForeground(new Color(139, 69, 19));
        
        JTextArea instructionsText = new JTextArea(
            "1. 윷을 던져 이동할 칸 수를 결정합니다.\n" +
            "2. 도(Do): 1칸, 개(Gae): 2칸, 걸(Geol): 3칸\n" +
            "   윷(Yut): 4칸, 모(Mo): 5칸 이동\n" +
            "3. 말을 클릭하여 이동시킵니다.\n" +
            "4. 윷이나 모가 나오면 한 번 더 던집니다.\n" +
            "5. 상대방 말을 잡으면 한 번 더 던집니다.\n" +
            "6. 먼저 4개의 말을 모두 완주시키는 플레이어가 승리합니다."
        );
        instructionsText.setFont(new Font("SansSerif", Font.PLAIN, 12));
        instructionsText.setEditable(false);
        instructionsText.setLineWrap(true);
        instructionsText.setWrapStyleWord(true);
        instructionsText.setBackground(new Color(255, 250, 240));
        instructionsText.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        panel.add(titleLabel, BorderLayout.NORTH);
        panel.add(instructionsText, BorderLayout.CENTER);
        
        return panel;
    }
    
    /**
     * Creates a footer panel with credits.
     */
    private JPanel createFooterPanel() {
        JPanel footerPanel = new JPanel(new BorderLayout());
        footerPanel.setBackground(new Color(200, 180, 150));
        footerPanel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createMatteBorder(2, 0, 0, 0, new Color(139, 69, 19)),
            BorderFactory.createEmptyBorder(5, 20, 5, 20)
        ));
        
        JLabel creditsLabel = new JLabel("© 2025 한국 윷놀이 프로젝트", JLabel.CENTER);
        creditsLabel.setFont(new Font("SansSerif", Font.PLAIN, 12));
        creditsLabel.setForeground(new Color(80, 30, 0));
        
        footerPanel.add(creditsLabel, BorderLayout.CENTER);
        
        return footerPanel;
    }
    
    /**
     * Sets up event listeners for buttons and other interactive components.
     */
    private void setupEventListeners() {
        // New Game button action
        newGameButton.addActionListener(e -> {
            initializeGame();
            yutStickPanel.setGame(gameBoard.getGame());
            yutStickPanel.reset();
            gameBoard.reset();
            endTurnButton.setEnabled(false);
            gameBoard.repaint();
            
            // Ensure throw button is enabled for first player
            yutStickPanel.setThrowEnabled(true);
            System.out.println("New game started, current player: " + 
                             gameBoard.getGame().getCurrentPlayer().getName());
        });
        
        // End Turn button action
        endTurnButton.addActionListener(e -> {
            // Use the new handleEndTurn method instead of manually updating
            gameBoard.handleEndTurn();
            
            // Update button state
            endTurnButton.setEnabled(false);
            
            // No need to call reset or manually update messages, handleEndTurn does it all
            System.out.println("Turn ended, current player: " + 
                             gameBoard.getGame().getCurrentPlayer().getName());
        });
        
        // Listen for game state changes
        yutStickPanel.addYutThrowListener(new YutStickPanel.YutThrowListener() {
            @Override
            public void onYutThrown(int result) {
                gameBoard.updateAfterRoll(result);
                // Always enable End Turn button after any roll
                endTurnButton.setEnabled(true);
            }
        });
    }
    
    /**
     * The main method to start the application.
     * 
     * @param args Command line arguments (not used)
     */
    public static void main(String[] args) {
        // Set Nimbus look and feel if available
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
            // If Nimbus is not available, fall back to the default look and feel
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception ex) {
                // Not critical if it fails, the default Java look and feel will be used
            }
        }
        
        // Start the application on the EDT
        SwingUtilities.invokeLater(() -> {
            new YutNoriApp();
        });
    }
} 